<?php

namespace addons\yunfood\model;

use addons\yunfood\library\ModelTrait;
use app\common\model\User;
use think\Db;
use think\Exception;
use think\Model;
use traits\model\SoftDelete;

/**
 * 储值账户模型
 */
class FundUser extends Model
{
    use ModelTrait;
    use SoftDelete;

    // 表名,不含前缀
    protected $name = 'yunfood_fund_user';

    // 自动写入时间戳字段
    protected $autoWriteTimestamp = true;

    // 定义时间戳字段名
    protected $deleteTime = 'deleted_at';
    protected $updateTime = 'updated_at';
    protected $createTime = 'created_at';

    // 不显示的字段
    protected $hidden = ['deleted_at'];

    protected $resultSetType = 'collection';

    // 用户数据
    public function userData()
    {
        return $this->hasOne(User::class, 'id', 'user_id');
    }

    // 状态
    const STATUS_NORMAL = 1;
    const STATUS_HIDDEN = 2;

    public static function getStatusList()
    {
        return [self::STATUS_NORMAL => __('Normal'), self::STATUS_HIDDEN => __('屏蔽')];
    }

    public function getStatusTextAttr($value, $data)
    {
        $optionList = self::getStatusList();

        return $optionList[$data['status']] ?? $data['status'];
    }

    /**
     * 增减余额
     *
     * @param $userId
     * @param $action
     * @param int $amount
     * @param string $sourceType
     * @param int $sourceId
     * @param string $fromType
     * @param int $fromId
     * @throws Exception
     * @throws \think\exception\DbException
     */
    public static function amountCounter(
        $userId,
        $action,
        $amount = 0,
        $useLeft = false,
        $sourceType = '',
        $sourceId = 0,
        $fromType = '',
        $fromId = 0,
        $fundUserId = 0
    ) {
        if (! $amount) {
            throw new Exception('金额不能为空');
        }

        // 初始化账户
        if ($fundUserId) {
            $fundUser = FundUser::get($fundUserId);
        } else {
            $fundUser = FundUser::get(['user_id' => $userId]);
        }
        if (! $fundUser) {
            throw new Exception('余额账户未开通');
        }
        if (! in_array($action, [
            FundRecord::ACTION_SYSTEM_ROLLBACK,
            FundRecord::ACTION_MANUAL_PLUS,
            FundRecord::ACTION_MANUAL_MINUS
        ])) {
            if ($fundUser->status == FundUser::STATUS_HIDDEN) {
                throw new Exception('余额账户被禁用');
            }
        }

        // 剩余校验
        if ($amount < 0 && ! in_array($action, [
                FundRecord::ACTION_SYSTEM_ROLLBACK,
                FundRecord::ACTION_MANUAL_MINUS
            ])) {
            if ($fundUser->amount_left == 0) {
                return 0;
            }
            if ($fundUser->amount_left < abs($amount)) {
                if ($useLeft) {
                    $amount = -$fundUser->amount_left;  //  余额支付
                } else {
                    throw new Exception('余额不够');
                }
            }
        }

        // 余额记录
        $fundRecord = new FundRecord();
        $fundRecord->fund_user_id = $fundUser->id;
        $fundRecord->user_id = $fundUser->user_id;
        $fundRecord->action = $action;
        $fundRecord->source_type = $sourceType;
        $fundRecord->source_id = $sourceId;
        $fundRecord->from_type = $fromType;
        $fundRecord->from_id = $fromId;
        $fundRecord->amount = $amount;
        $fundRecord->after_amount = $fundUser->amount_left + $amount;

        // 增减余额
        Db::transaction(function () use ($fundRecord) {
            // 保存记录
            $fundRecord->save();

            // 处理账户
            $query = FundUser::where(['user_id' => $fundRecord->user_id]);
            if ($fundRecord->amount > 0) {  // 正常获得
                $tAmount = $fundRecord->amount;
                if ($fundRecord->action == FundRecord::ACTION_REFUND) {
                    $query->inc('amount_left', $tAmount)->inc('amount_back', $tAmount)->update();
                } else {
                    $query->inc('amount_left', $tAmount)->inc('amount_gain', $tAmount)->update();
                }
            } else {
                $absAmount = abs($fundRecord->amount);
                if (in_array($fundRecord->action, [
                    FundRecord::ACTION_SYSTEM_ROLLBACK,
                    FundRecord::ACTION_MANUAL_MINUS
                ])) {  // 人工减少
                    $query->dec('amount_left', $absAmount)->dec('amount_gain', $absAmount)->update();
                } else {  // 正常消费
                    $query->where('amount_left', '>=', $absAmount);
                    $row = $query->dec('amount_left', $absAmount)->inc('amount_use', $absAmount)->update();
                    if (! $row) {
                        throw new Exception('余额不够');
                    }
                }
            }
        });

        return abs($amount);
    }
}
